using DocumentCreationSystem.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using System.Text.Json;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace DocumentCreationSystem.Services
{
    /// <summary>
    /// 版本控制服务 - 提供文档版本管理、差异比较、回滚等功能
    /// </summary>
    public interface IVersionControlService
    {
        Task<VersionSnapshot> CreateSnapshotAsync(string resourceId, string userId, string description);
        Task<List<VersionSnapshot>> GetVersionHistoryAsync(string resourceId, int limit = 50);
        Task<VersionSnapshot?> GetVersionAsync(string resourceId, string versionId);
        Task<bool> RevertToVersionAsync(string resourceId, string versionId, string userId);
        Task<VersionDiff> CompareVersionsAsync(string resourceId, string fromVersionId, string toVersionId);
        Task<List<VersionBranch>> GetBranchesAsync(string resourceId);
        Task<VersionBranch> CreateBranchAsync(string resourceId, string branchName, string fromVersionId, string userId);
        Task<MergeResult> MergeBranchAsync(string resourceId, string sourceBranch, string targetBranch, string userId);
        Task<bool> DeleteVersionAsync(string resourceId, string versionId);
        Task<VersionStatistics> GetVersionStatisticsAsync(string resourceId);
    }

    public class VersionControlService : IVersionControlService
    {
        private readonly ILogger<VersionControlService> _logger;
        private readonly IDataStorageService _dataStorage;
        private readonly string _versionsPath;

        public VersionControlService(
            ILogger<VersionControlService> logger,
            IDataStorageService dataStorage,
            IConfiguration configuration)
        {
            _logger = logger;
            _dataStorage = dataStorage;
            _versionsPath = configuration["VersionControl:StoragePath"] ?? "versions";
            
            // 确保版本存储目录存在
            Directory.CreateDirectory(_versionsPath);
        }

        /// <summary>
        /// 创建版本快照
        /// </summary>
        public async Task<VersionSnapshot> CreateSnapshotAsync(string resourceId, string userId, string description)
        {
            try
            {
                _logger.LogInformation($"创建版本快照: {resourceId}");

                // 读取当前资源内容
                var currentContent = await ReadResourceContentAsync(resourceId);
                var contentHash = ComputeContentHash(currentContent);

                // 检查是否有内容变更
                var lastVersion = await GetLatestVersionAsync(resourceId);
                if (lastVersion != null && lastVersion.ContentHash == contentHash)
                {
                    _logger.LogInformation($"内容未变更，跳过快照创建: {resourceId}");
                    return lastVersion;
                }

                var snapshot = new VersionSnapshot
                {
                    Id = Guid.NewGuid().ToString(),
                    ResourceId = resourceId,
                    VersionNumber = await GetNextVersionNumberAsync(resourceId),
                    CreatedBy = userId,
                    CreatedAt = DateTime.Now,
                    Description = description,
                    ContentHash = contentHash,
                    ContentSize = currentContent.Length,
                    BranchName = "main"
                };

                // 保存快照内容
                var snapshotPath = GetSnapshotPath(resourceId, snapshot.Id);
                await File.WriteAllTextAsync(snapshotPath, currentContent);

                // 保存快照元数据
                await SaveSnapshotMetadataAsync(snapshot);

                // 计算与上一版本的差异
                if (lastVersion != null)
                {
                    snapshot.ChangesSummary = await GenerateChangesSummaryAsync(resourceId, lastVersion.Id, snapshot.Id);
                }

                _logger.LogInformation($"版本快照创建完成: {resourceId} v{snapshot.VersionNumber}");
                return snapshot;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"创建版本快照失败: {resourceId}");
                throw;
            }
        }

        /// <summary>
        /// 获取版本历史
        /// </summary>
        public async Task<List<VersionSnapshot>> GetVersionHistoryAsync(string resourceId, int limit = 50)
        {
            try
            {
                var metadataPath = GetResourceMetadataPath(resourceId);
                if (!File.Exists(metadataPath))
                {
                    return new List<VersionSnapshot>();
                }

                var metadataJson = await File.ReadAllTextAsync(metadataPath);
                var metadata = JsonSerializer.Deserialize<ResourceVersionMetadata>(metadataJson);

                return metadata?.Versions
                    .OrderByDescending(v => v.CreatedAt)
                    .Take(limit)
                    .ToList() ?? new List<VersionSnapshot>();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取版本历史失败: {resourceId}");
                return new List<VersionSnapshot>();
            }
        }

        /// <summary>
        /// 获取特定版本
        /// </summary>
        public async Task<VersionSnapshot?> GetVersionAsync(string resourceId, string versionId)
        {
            try
            {
                var versions = await GetVersionHistoryAsync(resourceId);
                return versions.FirstOrDefault(v => v.Id == versionId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取版本失败: {resourceId}, 版本: {versionId}");
                return null;
            }
        }

        /// <summary>
        /// 回滚到指定版本
        /// </summary>
        public async Task<bool> RevertToVersionAsync(string resourceId, string versionId, string userId)
        {
            try
            {
                _logger.LogInformation($"回滚版本: {resourceId} -> {versionId}");

                var targetVersion = await GetVersionAsync(resourceId, versionId);
                if (targetVersion == null)
                {
                    _logger.LogWarning($"目标版本不存在: {versionId}");
                    return false;
                }

                // 读取目标版本内容
                var snapshotPath = GetSnapshotPath(resourceId, versionId);
                if (!File.Exists(snapshotPath))
                {
                    _logger.LogWarning($"版本快照文件不存在: {snapshotPath}");
                    return false;
                }

                var versionContent = await File.ReadAllTextAsync(snapshotPath);

                // 恢复资源内容
                await WriteResourceContentAsync(resourceId, versionContent);

                // 创建回滚快照
                await CreateSnapshotAsync(resourceId, userId, $"回滚到版本 v{targetVersion.VersionNumber}");

                _logger.LogInformation($"版本回滚完成: {resourceId} -> v{targetVersion.VersionNumber}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"版本回滚失败: {resourceId} -> {versionId}");
                return false;
            }
        }

        /// <summary>
        /// 比较版本差异
        /// </summary>
        public async Task<VersionDiff> CompareVersionsAsync(string resourceId, string fromVersionId, string toVersionId)
        {
            try
            {
                _logger.LogInformation($"比较版本差异: {resourceId} {fromVersionId} -> {toVersionId}");

                var fromContent = await GetVersionContentAsync(resourceId, fromVersionId);
                var toContent = await GetVersionContentAsync(resourceId, toVersionId);

                var diff = new VersionDiff
                {
                    ResourceId = resourceId,
                    FromVersionId = fromVersionId,
                    ToVersionId = toVersionId,
                    ComparedAt = DateTime.Now
                };

                // 计算差异
                diff.Changes = await ComputeTextDifferencesAsync(fromContent, toContent);
                diff.AddedLines = diff.Changes.Count(c => c.Type == DiffChangeType.Added);
                diff.DeletedLines = diff.Changes.Count(c => c.Type == DiffChangeType.Deleted);
                diff.ModifiedLines = diff.Changes.Count(c => c.Type == DiffChangeType.Modified);

                // 生成差异摘要
                diff.Summary = GenerateDiffSummary(diff);

                return diff;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"比较版本差异失败: {resourceId}");
                throw;
            }
        }

        /// <summary>
        /// 获取分支列表
        /// </summary>
        public async Task<List<VersionBranch>> GetBranchesAsync(string resourceId)
        {
            try
            {
                var metadataPath = GetResourceMetadataPath(resourceId);
                if (!File.Exists(metadataPath))
                {
                    return new List<VersionBranch> { CreateDefaultBranch() };
                }

                var metadataJson = await File.ReadAllTextAsync(metadataPath);
                var metadata = JsonSerializer.Deserialize<ResourceVersionMetadata>(metadataJson);

                return metadata?.Branches ?? new List<VersionBranch> { CreateDefaultBranch() };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取分支列表失败: {resourceId}");
                return new List<VersionBranch>();
            }
        }

        /// <summary>
        /// 创建分支
        /// </summary>
        public async Task<VersionBranch> CreateBranchAsync(string resourceId, string branchName, string fromVersionId, string userId)
        {
            try
            {
                _logger.LogInformation($"创建分支: {resourceId} -> {branchName} from {fromVersionId}");

                var branch = new VersionBranch
                {
                    Id = Guid.NewGuid().ToString(),
                    Name = branchName,
                    CreatedBy = userId,
                    CreatedAt = DateTime.Now,
                    BaseVersionId = fromVersionId,
                    IsActive = true
                };

                // 更新元数据
                var metadata = await GetOrCreateResourceMetadataAsync(resourceId);
                metadata.Branches.Add(branch);
                await SaveResourceMetadataAsync(resourceId, metadata);

                _logger.LogInformation($"分支创建完成: {branchName}");
                return branch;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"创建分支失败: {resourceId} -> {branchName}");
                throw;
            }
        }

        /// <summary>
        /// 合并分支
        /// </summary>
        public async Task<MergeResult> MergeBranchAsync(string resourceId, string sourceBranch, string targetBranch, string userId)
        {
            try
            {
                _logger.LogInformation($"合并分支: {sourceBranch} -> {targetBranch}");

                var result = new MergeResult
                {
                    ResourceId = resourceId,
                    SourceBranch = sourceBranch,
                    TargetBranch = targetBranch,
                    MergedBy = userId,
                    MergedAt = DateTime.Now
                };

                // 获取分支的最新版本
                var sourceVersion = await GetLatestVersionInBranchAsync(resourceId, sourceBranch);
                var targetVersion = await GetLatestVersionInBranchAsync(resourceId, targetBranch);

                if (sourceVersion == null || targetVersion == null)
                {
                    result.Success = false;
                    result.ErrorMessage = "无法找到分支的最新版本";
                    return result;
                }

                // 检查冲突
                var conflicts = await DetectMergeConflictsAsync(resourceId, sourceVersion.Id, targetVersion.Id);
                if (conflicts.Any())
                {
                    result.Success = false;
                    result.Conflicts = conflicts;
                    result.ErrorMessage = $"检测到 {conflicts.Count} 个合并冲突";
                    return result;
                }

                // 执行合并
                var mergedContent = await PerformMergeAsync(resourceId, sourceVersion.Id, targetVersion.Id);
                await WriteResourceContentAsync(resourceId, mergedContent);

                // 创建合并快照
                var mergeSnapshot = await CreateSnapshotAsync(resourceId, userId, $"合并分支 {sourceBranch} 到 {targetBranch}");
                mergeSnapshot.BranchName = targetBranch;

                result.Success = true;
                result.MergeCommitId = mergeSnapshot.Id;

                _logger.LogInformation($"分支合并完成: {sourceBranch} -> {targetBranch}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"分支合并失败: {sourceBranch} -> {targetBranch}");
                return new MergeResult
                {
                    Success = false,
                    ErrorMessage = ex.Message
                };
            }
        }

        /// <summary>
        /// 删除版本
        /// </summary>
        public async Task<bool> DeleteVersionAsync(string resourceId, string versionId)
        {
            try
            {
                _logger.LogInformation($"删除版本: {resourceId} -> {versionId}");

                // 删除快照文件
                var snapshotPath = GetSnapshotPath(resourceId, versionId);
                if (File.Exists(snapshotPath))
                {
                    File.Delete(snapshotPath);
                }

                // 更新元数据
                var metadata = await GetOrCreateResourceMetadataAsync(resourceId);
                metadata.Versions.RemoveAll(v => v.Id == versionId);
                await SaveResourceMetadataAsync(resourceId, metadata);

                _logger.LogInformation($"版本删除完成: {versionId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"删除版本失败: {resourceId} -> {versionId}");
                return false;
            }
        }

        /// <summary>
        /// 获取版本统计信息
        /// </summary>
        public async Task<VersionStatistics> GetVersionStatisticsAsync(string resourceId)
        {
            try
            {
                var versions = await GetVersionHistoryAsync(resourceId, int.MaxValue);
                var branches = await GetBranchesAsync(resourceId);

                var stats = new VersionStatistics
                {
                    ResourceId = resourceId,
                    TotalVersions = versions.Count,
                    TotalBranches = branches.Count,
                    FirstVersionDate = versions.LastOrDefault()?.CreatedAt,
                    LastVersionDate = versions.FirstOrDefault()?.CreatedAt,
                    TotalSize = versions.Sum(v => v.ContentSize),
                    Contributors = versions.Select(v => v.CreatedBy).Distinct().ToList(),
                    VersionsByMonth = GroupVersionsByMonth(versions),
                    AverageVersionSize = versions.Any() ? versions.Average(v => v.ContentSize) : 0
                };

                return stats;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取版本统计失败: {resourceId}");
                throw;
            }
        }

        #region 私有辅助方法

        private async Task<string> ReadResourceContentAsync(string resourceId)
        {
            // 这里应该根据资源类型读取内容
            // 简化实现，假设资源是文本文件
            var resourcePath = GetResourcePath(resourceId);
            return File.Exists(resourcePath) ? await File.ReadAllTextAsync(resourcePath) : string.Empty;
        }

        private async Task WriteResourceContentAsync(string resourceId, string content)
        {
            var resourcePath = GetResourcePath(resourceId);
            await File.WriteAllTextAsync(resourcePath, content);
        }

        private string ComputeContentHash(string content)
        {
            using var sha256 = SHA256.Create();
            var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(content));
            return Convert.ToBase64String(hashBytes);
        }

        private async Task<int> GetNextVersionNumberAsync(string resourceId)
        {
            var versions = await GetVersionHistoryAsync(resourceId);
            return versions.Any() ? versions.Max(v => v.VersionNumber) + 1 : 1;
        }

        private async Task<VersionSnapshot?> GetLatestVersionAsync(string resourceId)
        {
            var versions = await GetVersionHistoryAsync(resourceId, 1);
            return versions.FirstOrDefault();
        }

        private async Task<VersionSnapshot?> GetLatestVersionInBranchAsync(string resourceId, string branchName)
        {
            var versions = await GetVersionHistoryAsync(resourceId);
            return versions.Where(v => v.BranchName == branchName).FirstOrDefault();
        }

        private string GetSnapshotPath(string resourceId, string versionId)
        {
            var resourceDir = Path.Combine(_versionsPath, resourceId);
            Directory.CreateDirectory(resourceDir);
            return Path.Combine(resourceDir, $"{versionId}.snapshot");
        }

        private string GetResourceMetadataPath(string resourceId)
        {
            var resourceDir = Path.Combine(_versionsPath, resourceId);
            Directory.CreateDirectory(resourceDir);
            return Path.Combine(resourceDir, "metadata.json");
        }

        private string GetResourcePath(string resourceId)
        {
            // 简化实现，实际应该根据资源类型确定路径
            return Path.Combine("resources", $"{resourceId}.txt");
        }

        private async Task SaveSnapshotMetadataAsync(VersionSnapshot snapshot)
        {
            var metadata = await GetOrCreateResourceMetadataAsync(snapshot.ResourceId);
            metadata.Versions.Add(snapshot);
            await SaveResourceMetadataAsync(snapshot.ResourceId, metadata);
        }

        private async Task<ResourceVersionMetadata> GetOrCreateResourceMetadataAsync(string resourceId)
        {
            var metadataPath = GetResourceMetadataPath(resourceId);
            if (File.Exists(metadataPath))
            {
                var json = await File.ReadAllTextAsync(metadataPath);
                return JsonSerializer.Deserialize<ResourceVersionMetadata>(json) ?? new ResourceVersionMetadata();
            }

            return new ResourceVersionMetadata
            {
                ResourceId = resourceId,
                CreatedAt = DateTime.Now,
                Branches = new List<VersionBranch> { CreateDefaultBranch() }
            };
        }

        private async Task SaveResourceMetadataAsync(string resourceId, ResourceVersionMetadata metadata)
        {
            var metadataPath = GetResourceMetadataPath(resourceId);
            var json = JsonSerializer.Serialize(metadata, new JsonSerializerOptions { WriteIndented = true });
            await File.WriteAllTextAsync(metadataPath, json);
        }

        private VersionBranch CreateDefaultBranch()
        {
            return new VersionBranch
            {
                Id = "main",
                Name = "main",
                CreatedAt = DateTime.Now,
                IsActive = true
            };
        }

        private async Task<string> GetVersionContentAsync(string resourceId, string versionId)
        {
            var snapshotPath = GetSnapshotPath(resourceId, versionId);
            return File.Exists(snapshotPath) ? await File.ReadAllTextAsync(snapshotPath) : string.Empty;
        }

        private async Task<List<DiffChange>> ComputeTextDifferencesAsync(string fromContent, string toContent)
        {
            // 简化的差异计算实现
            // 实际应用中可以使用更复杂的差异算法，如Myers算法
            var changes = new List<DiffChange>();
            
            var fromLines = fromContent.Split('\n');
            var toLines = toContent.Split('\n');

            // 简单的逐行比较
            var maxLines = Math.Max(fromLines.Length, toLines.Length);
            for (int i = 0; i < maxLines; i++)
            {
                var fromLine = i < fromLines.Length ? fromLines[i] : null;
                var toLine = i < toLines.Length ? toLines[i] : null;

                if (fromLine == null && toLine != null)
                {
                    changes.Add(new DiffChange
                    {
                        Type = DiffChangeType.Added,
                        LineNumber = i + 1,
                        Content = toLine
                    });
                }
                else if (fromLine != null && toLine == null)
                {
                    changes.Add(new DiffChange
                    {
                        Type = DiffChangeType.Deleted,
                        LineNumber = i + 1,
                        Content = fromLine
                    });
                }
                else if (fromLine != toLine)
                {
                    changes.Add(new DiffChange
                    {
                        Type = DiffChangeType.Modified,
                        LineNumber = i + 1,
                        OldContent = fromLine,
                        Content = toLine
                    });
                }
            }

            return changes;
        }

        private string GenerateDiffSummary(VersionDiff diff)
        {
            return $"添加 {diff.AddedLines} 行，删除 {diff.DeletedLines} 行，修改 {diff.ModifiedLines} 行";
        }

        private async Task<string> GenerateChangesSummaryAsync(string resourceId, string fromVersionId, string toVersionId)
        {
            var diff = await CompareVersionsAsync(resourceId, fromVersionId, toVersionId);
            return diff.Summary;
        }

        private async Task<List<MergeConflict>> DetectMergeConflictsAsync(string resourceId, string sourceVersionId, string targetVersionId)
        {
            // 简化的冲突检测
            var conflicts = new List<MergeConflict>();
            
            // 实际实现应该检查两个版本之间的冲突
            await Task.Delay(10);
            
            return conflicts;
        }

        private async Task<string> PerformMergeAsync(string resourceId, string sourceVersionId, string targetVersionId)
        {
            // 简化的合并实现
            var sourceContent = await GetVersionContentAsync(resourceId, sourceVersionId);
            var targetContent = await GetVersionContentAsync(resourceId, targetVersionId);
            
            // 实际实现应该执行智能合并
            return targetContent + "\n" + sourceContent;
        }

        private Dictionary<string, int> GroupVersionsByMonth(List<VersionSnapshot> versions)
        {
            return versions
                .GroupBy(v => v.CreatedAt.ToString("yyyy-MM"))
                .ToDictionary(g => g.Key, g => g.Count());
        }

        #endregion
    }
}
